<script setup lang="ts">
import type { Rule } from 'ant-design-vue/es/form'
import { codeValidator, nameValidator } from '~/utils/form-validator.ts'
import type { MenuReq, MenuResp } from '~/api/setting/model/menu.ts'
import { createMenuApi, modifyMenuApi, queryMenuTreeListApi } from '~/api/setting/menu.ts'

const props = defineProps({
  menuData: Object,
  optType: {
    type: String,
    default: 'create',
  },
})

const emits = defineEmits(['onSaveSuccess'])

const message = useMessage()

const menuReq = ref<MenuReq>({
  parentId: undefined,
  icon: 'ProfileOutlined',
  menuTitle: undefined,
  menuCode: undefined,
  routerPath: undefined,
  routerName: undefined,
  componentPath: undefined,
  redirect: undefined,
  type: 0, // 权限类型：0->目录；1->菜单；
  isExtId: 0, // 是否外部链接：0->否；1->是
  hideInMenuId: 0, // 显示隐藏菜单：0->隐藏；1->显示
  hideBreadcrumbId: 0, // 显示隐藏面包屑：0->隐藏；1->显示
  hideChildrenInMenuId: 0, // 显示隐藏子级菜单：0->隐藏；1->显示
  keepAliveId: 0, // 是否保持页面状态：0->不保持，1->保持
  sort: 1,
  note: undefined,
})

const menuCreateFormRef = ref()
const rules: Record<string, Rule[]> = {
  parentId: [
    { required: true, message: '请选择父级目录' },
  ],
  menuTitle: [
    { required: true, message: '请输入菜单名称' },
    { validator: nameValidator, trigger: 'blur' },
  ],
  menuCode: [
    { required: true, message: '请输入菜单编码' },
    { validator: codeValidator, trigger: 'blur' },
  ],
  routerPath: [
    { required: true, message: '请输入菜单路径' },
  ],
  routerName: [
    { required: true, message: '请输入菜单KEY' },
  ],
  componentPath: [
    { required: true, message: '请输入组件路径' },
  ],
  type: [
    { required: true, message: '请选择菜单类型' },
  ],
  isExtId: [
    { required: true, message: '请选择是否外部链接' },
  ],
  hideInMenuId: [
    { required: true, message: '请选择是否展示在菜单中' },
  ],
  hideBreadcrumbId: [
    { required: true, message: '请选择是否展示面包屑' },
  ],
  hideChildrenInMenuId: [
    { required: true, message: '请选择是否展示子菜单' },
  ],
  keepAliveId: [
    { required: true, message: '请选择是否保持页面' },
  ],
  sort: [
    { required: true, message: '请输入排序' },
  ],
}

const dataSource = shallowRef<MenuResp[]>([])
const loading = shallowRef(false)

/**
 * 初始化菜单
 */
async function init() {
  if (props.menuData && props.menuData.id) {
    menuReq.value = props.menuData
  }

  if (loading.value) {
    return
  }
  loading.value = true
  try {
    const rootMenu: MenuResp[] = [{
      id: '0',
      menuTitle: '根目录',
    }]
    rootMenu[0].children = await queryMenuTreeListApi()
    dataSource.value = rootMenu
  } catch (e) {
    console.log(e)
  } finally {
    loading.value = false
  }
}

const confirmLoading = shallowRef(false)

async function onSaveMenu() {
  if (props.optType === 'create') {
    await onCreateMenu()
  } else {
    await onEditMenu()
  }
}

/**
 *  添加菜单
 */
async function onCreateMenu() {
  menuCreateFormRef.value
    .validate()
    .then(() => {
      confirmLoading.value = true
      createMenuApi(menuReq.value).then((response) => {
        if (response) {
          message.success('新建成功')
          emits('onSaveSuccess', 'create')
        }
      }).finally(() => {
        confirmLoading.value = false
        close()
      })
    })
    .catch(() => {
      console.log('menuCreateFormRef::error')
    })
}

/**
 *  编辑菜单
 */
async function onEditMenu() {
  menuCreateFormRef.value
    .validate()
    .then(() => {
      confirmLoading.value = true
      modifyMenuApi(menuReq.value).then((response) => {
        if (response) {
          message.success('修改成功')
          emits('onSaveSuccess', 'edit')
        }
      }).finally(() => {
        confirmLoading.value = false
        close()
      })
    })
    .catch(() => {
      console.log('menuCreateFormRef::error')
    })
}

onMounted(() => {
  init()
})
</script>

<template>
  <a-modal title="编辑菜单" width="800px" :confirm-loading="confirmLoading" @ok="onSaveMenu">
    <a-space direction="vertical" size="large" class="w-full">
      <a-form
        ref="menuCreateFormRef"
        :model="menuReq"
        :rules="rules"
        :label-col="{ span: 6 }"
        :wrapper-col="{ span: 14 }"
        layout="horizontal"
      >
        <a-form-item name="parentId" label="父级目录">
          <a-tree-select
            v-model:value="menuReq.parentId"
            placeholder="请输入菜单名称"
            :tree-data="dataSource"
            :field-names="{ value: 'id', label: 'menuTitle' }"
            tree-node-filter-prop="label"
            tree-default-expand-all
            allow-clear
          />
        </a-form-item>
        <a-form-item name="icon" label="图标">
          <a-input v-model:value="menuReq.icon" placeholder="请输入图标(ProfileOutlined)" allow-clear />
        </a-form-item>
        <a-form-item name="menuTitle" label="菜单名称">
          <a-input v-model:value="menuReq.menuTitle" placeholder="请输入菜单名称" allow-clear />
        </a-form-item>
        <a-form-item name="menuCode" label="菜单编码">
          <a-input v-model:value="menuReq.menuCode" placeholder="请输入菜单编码" allow-clear />
        </a-form-item>
        <a-form-item name="routerName" label="菜单Key">
          <a-input v-model:value="menuReq.routerName" placeholder="请输入菜单KEY" allow-clear />
        </a-form-item>
        <a-form-item name="routerPath" label="菜单地址">
          <a-input v-model:value="menuReq.routerPath" placeholder="请输入菜单地址" allow-clear />
        </a-form-item>
        <a-form-item name="componentPath" label="组件地址">
          <a-input v-model:value="menuReq.componentPath" placeholder="请输入组件地址" allow-clear />
        </a-form-item>
        <a-form-item name="redirect" label="重定向">
          <a-input v-model:value="menuReq.redirect" placeholder="请输入组件地址" allow-clear />
        </a-form-item>
        <a-form-item name="type" label="菜单类型">
          <a-radio-group v-model:value="menuReq.type">
            <a-radio-button :value="0">
              目录
            </a-radio-button>
            <a-radio-button :value="1">
              菜单
            </a-radio-button>
          </a-radio-group>
        </a-form-item>
        <a-form-item name="isExtId" label="外部链接">
          <a-switch
            v-model:checked="menuReq.isExtId"
            checked-children="是"
            un-checked-children="否"
            :checked-value="1"
            :un-checked-value="0"
          />
        </a-form-item>
        <a-form-item name="hideInMenuId" label="是否展示在菜单中">
          <a-switch
            v-model:checked="menuReq.hideInMenuId"
            checked-children="展示"
            un-checked-children="隐藏"
            :checked-value="1"
            :un-checked-value="0"
          />
        </a-form-item>
        <a-form-item name="hideBreadcrumbId" label="是否展示面包屑">
          <a-switch
            v-model:checked="menuReq.hideBreadcrumbId"
            checked-children="展示"
            un-checked-children="隐藏"
            :checked-value="1"
            :un-checked-value="0"
          />
        </a-form-item>
        <a-form-item name="hideChildrenInMenuId" label="是否展示子菜单">
          <a-switch
            v-model:checked="menuReq.hideChildrenInMenuId"
            checked-children="展示"
            un-checked-children="隐藏"
            :checked-value="1"
            :un-checked-value="0"
          />
        </a-form-item>
        <a-form-item name="keepAliveId" label="是否保持页面">
          <a-switch
            v-model:checked="menuReq.keepAliveId"
            checked-children="展示"
            un-checked-children="隐藏"
            :checked-value="1"
            :un-checked-value="0"
          />
        </a-form-item>
        <a-form-item name="sort" label="排序">
          <a-input-number v-model:value="menuReq.sort" placeholder="排序" allow-clear />
        </a-form-item>
        <a-form-item name="note" label="备注">
          <a-textarea
            v-model:value="menuReq.note"
            :rows="4"
            placeholder="请输入备注"
            allow-clear
          />
        </a-form-item>
      </a-form>
    </a-space>
  </a-modal>
</template>

<style lang="less" scoped>
.avatar-uploader {
  .ant-upload {
    width: 128px;
    height: 128px;
  }
}

.avatar-uploader-img {
  width: 100px;
  height: 100px;
  border-radius: 8px;
}

.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
</style>
